import { Uri } from "vscode";
import { Architecture } from "../../../common/utils/platform";
import { BasicVersionInfo, VersionInfo } from "../../../common/utils/version";

/**
 * IDs for the various supported EQ environments.
 */
export enum EQEnvKind {
    Unknown = 'unknown',
    Conda = 'virt-conda',
    OtherGlobal = 'global-other',
    WindowsStore = "windows-store",
}

export const virtualEnvKinds = [
    EQEnvKind.Conda,
];

export const globallyInstalledEnvKinds = [
    EQEnvKind.Unknown,
];

export interface EnvPathType {
    /**
     * Path to environment folder or path to interpreter that uniquely identifies an environment.
     * Virtual environments lacking an interpreter are identified by environment folder paths,
     * whereas other envs can be identified using interpreter path.
     */
    path: string;
    pathType: 'envFolderPath' | 'interpreterPath';
}

/**
 * Information about a file.
 */
export type FileInfo = {
    filename: string;
    ctime: number;
    mtime: number;
};

/**
 * Information about a EQ binary/executable.
 */
export type EQExecutableInfo = FileInfo & {
    sysPrefix: string;
};

type EQEnvBaseInfo = {
    id?: string;
    kind: EQEnvKind;
    executable: EQExecutableInfo;
    // One of (name, location) must be non-empty.
    name: string;
    location: string;
    // Other possible fields:
    // * managed: boolean (if the env is "managed")
    // * parent: EQEnvBaseInfo (the env from which this one was created)
    // * binDir: string (where env-installed executables are found)

    source: EQEnvSource[];
};

/**
 * Source types indicating how a particular environment was discovered.
 *
 * Notes: This is used in auto-selection to figure out which eq to select.
 * We added this field to support the existing mechanism in the extension to
 * calculate the auto-select eq.
 */
export enum EQEnvSource {
    /**
     * Environment was found via PATH env variable
     */
    PathEnvVar = 'path env var',
    /**
     * Environment was found in windows registry
     */
    WindowsRegistry = 'windows registry',
    // If source turns out to be useful we will expand this enum to contain more details sources.
}

/**
 * The possible EQ release levels.
 */
export enum EQReleaseLevel {
    Alpha = 'alpha',
    Beta = 'beta',
    Candidate = 'candidate',
    Final = 'final',
}

/**
 * Release information for a EQ version.
 */
export type EQVersionRelease = {
    level: EQReleaseLevel;
    serial: number;
};

/**
 * Version information for a EQ build/installation.
 *
 * @prop sysVersion - the raw text from `sys.version`
 */
export type EQVersion = BasicVersionInfo & {
    release?: EQVersionRelease;
    sysVersion?: string;
};


type EQDistroMetaInfo = {
    org: string;
    defaultDisplayName?: string;
};

type EQBuildInfo = {
    version: EQVersion; // incl. raw, AKA sys.version
    arch: Architecture;
};

type _EQEnvInfo = EQEnvBaseInfo & EQBuildInfo;

export type EQDistroInfo = EQDistroMetaInfo & {
    version?: VersionInfo;
    binDir?: string;
};

export type EQEnvInfo = _EQEnvInfo & {
    distro: EQDistroInfo;
    display?: string;
    detailedDisplayName?: string;
    searchLocation?: Uri;
};
export const UNKNOWN_EQ_VERSION: EQVersion = {
    major: -1,
    minor: -1,
    micro: -1,
    release: { level: EQReleaseLevel.Final, serial: -1 },
    sysVersion: undefined,
};
Object.freeze(UNKNOWN_EQ_VERSION);